package eCheque;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.security.Key;

import javax.crypto.Cipher;

/**
 * @author Steve Pennington
 *
 */
public class ChequeSender extends Thread {
	public static int PORT = 8190;

	private DigitalCertificate clientCertificate;
	private String hostname;
	private Key sessionKey;
	private String chequePath;
	private SendChequeHandler handler;

	public ChequeSender(String hostname,
			DigitalCertificate clientCertificate, Key sesisonKey, String chequePath, SendChequeHandler handler) {
		this.clientCertificate = clientCertificate;
		this.hostname = hostname;
		this.sessionKey = sesisonKey;
		this.chequePath = chequePath;
		this.handler = handler;
	}

	public void run() {
		Socket peerSocket = null;
		ObjectOutputStream outputStream = null;
		ObjectInputStream inputStream = null;
		FileInputStream chequeInputStream = null;
		try {
			peerSocket = new Socket(hostname, PORT);
			outputStream = new ObjectOutputStream(
					peerSocket.getOutputStream());
			inputStream = new ObjectInputStream(
					peerSocket.getInputStream());
			
			outputStream.writeObject(clientCertificate);
			outputStream.flush();
			
			DigitalCertificate peerCertificaticate = (DigitalCertificate) inputStream.readObject();
			
	
			// send session key
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.WRAP_MODE, peerCertificaticate.getpublicKey());
			byte[] wrappedKey = cipher.wrap(sessionKey);
			int keyLength = wrappedKey.length;
	
			outputStream.writeInt(keyLength);
			outputStream.flush();
	
			outputStream.write(wrappedKey);
			outputStream.flush();
	
			// send encrypted cheque.
			chequeInputStream = new FileInputStream(chequePath);
			byte[] buffer = new byte[1024];
			int numread;
			while ((numread = chequeInputStream.read(buffer)) >= 0) {
				outputStream.write(buffer, 0, numread);
			}
			outputStream.flush();
			handler.chequeSent();
		} catch(Exception e) {
			handler.chequeSendFailed(e);
		} finally {
			EChequeUtils.safeClose(outputStream);
			EChequeUtils.safeClose(inputStream);
			EChequeUtils.safeClose(chequeInputStream);
			try {
				if(peerSocket != null) {
					peerSocket.close();
				}
			} catch(IOException e) {}
		}
	}
}
